/*
 * Copyright 2009 XueSong Guo.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.webwheel;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

class FilterChainImpl implements FilterChain, WebContext {

    private int idx;
    private Filter[] filters;

    private Class<? extends Action> actionClass;
    private Map<Class, ResultInterpreter> interpreterMap;
    private String path;
    private Main main;
    private ServletContext servletContext;
    private HttpServletRequest request;
    private HttpServletResponse response;
    private Action action;

    FilterChainImpl(Filter[] filters, Class<? extends Action> actionClass, Map<Class, ResultInterpreter> interpreterMap,
                    String path, Main main, ServletContext servletContext, HttpServletRequest request, HttpServletResponse response) {
        this.filters = filters;
        this.actionClass = actionClass;
        this.interpreterMap = interpreterMap;
        this.path = path;
        this.main = main;
        this.servletContext = servletContext;
        this.request = request;
        this.response = response;
    }

    public WebContext getWebContext() {
        return this;
    }

    public Action getAction() {
        if (action == null) {
            action = main.getInstanceOf(actionClass);
        }
        return action;
    }

    public Class<? extends Action> getActionClass() {
        return actionClass;
    }

    @SuppressWarnings("unchecked")
    public boolean go() throws Exception {
        if (idx < filters.length) {
            return filters[idx++].process(this);
        }
        Action action = getAction();
        Object result = action.execute();
        if (result == null) return false;

        Class cls = result.getClass();
        do {
            ResultInterpreter it = interpreterMap.get(cls);
            if (it != null) {
                if (it.render(result, this, action)) return true;
            }
            for (Class inf : cls.getInterfaces()) {
                it = interpreterMap.get(inf);
                if (it != null) {
                    if (it.render(result, this, action)) return true;
                }
            }
            cls = cls.getSuperclass();
        } while (cls != null);
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/plain");
        response.getWriter().print(result);
        return true;
    }

    public String getPath() {
        return path;
    }

    public Main getMain() {
        return main;
    }

    public ServletContext getContext() {
        return servletContext;
    }

    public HttpServletRequest getRequest() {
        return request;
    }

    public HttpServletResponse getResponse() {
        return response;
    }
}
